package com.shenghuai.bclient.stores.adapter

import android.content.Context
import android.util.SparseBooleanArray
import android.view.ViewGroup
import androidx.annotation.LayoutRes
import androidx.core.util.getOrDefault
import androidx.recyclerview.widget.*
import com.example.androidreviewapp.R
import com.shenghuai.bclient.stores.util.ViewUtil

@Suppress("ConvertSecondaryConstructorToPrimary")
open class ListSimpleAdapter<T> : RecyclerBaseAdapter<T> {

    private val layoutId: Int

    var goodName: String = ""

    var checkedArray: SparseBooleanArray = SparseBooleanArray(5)

    fun isChecked(pos: Int): Boolean {
        return checkedArray.get(pos, false)
    }

    fun putChecked(pos: Int, isChecked: Boolean) {
        checkedArray.put(pos, isChecked)
    }

    fun allChecked() {
        if (itemCount <= 0)
            return
        for (i in 0 until itemCount) {
            checkedArray.put(i, true)
        }
        notifyDataSetChanged()
    }

    fun getCheckCount(): Int {
        var c = 0
        for (i in 0 until checkedArray.size()) {
            if (checkedArray.getOrDefault(i, false)) {
                c += 1
            }
        }
        return c
    }

    private var listDiffer: AsyncListDiffer<T>? = null

    fun setDiffer(listDiffer: AsyncListDiffer<T>) {
        this.listDiffer = listDiffer
    }

    fun setDiffer(itemCallback: DiffUtil.ItemCallback<T>) {
        setDiffer(AsyncListDiffer(object : ListUpdateCallback {
            override fun onInserted(position: Int, count: Int) {
                notifyItemRangeInserted(position, count)
            }

            override fun onRemoved(position: Int, count: Int) {
                notifyItemRangeRemoved(position, count)
            }

            override fun onMoved(fromPosition: Int, toPosition: Int) {
                notifyItemRangeRemoved(fromPosition, toPosition)
            }

            override fun onChanged(position: Int, count: Int, payload: Any?) {
                notifyItemRangeChanged(position, count, payload)
            }

        }, AsyncDifferConfig.Builder(itemCallback).build()))
    }

    fun getListDiffer(): AsyncListDiffer<T>? {
        return this.listDiffer
    }

    fun getListDifferCurrentList(): List<T>? {
        return listDiffer?.currentList
    }

    fun clear() {
        getListDiffer()?.submitList(emptyList())
    }

    override fun getDataList(): MutableList<T> {
        if (this.listDiffer != null) {
            return listDiffer?.currentList as MutableList
        }
        return super.getDataList()
    }

    var viewHolderRecycledCallback: Function1<ViewHolder, Unit>? = null

    override fun onViewRecycled(holder: ViewHolder) {
        super.onViewRecycled(holder)
        viewHolderRecycledCallback?.invoke(holder)
    }

    var holderDetachCallback: ((ViewHolder, Boolean) -> Unit)? = null

    override fun onViewAttachedToWindow(holder: ViewHolder) {
        super.onViewAttachedToWindow(holder)
        holderDetachCallback?.invoke(holder, true)
    }

    override fun onViewDetachedFromWindow(holder: ViewHolder) {
        super.onViewDetachedFromWindow(holder)
        holderDetachCallback?.invoke(holder, false)
    }

    override fun getItem(position: Int): T {
        if (this.listDiffer != null && position < itemCount)
            return dataList[position]
        return super.getItem(position)
    }

    fun getItem(predicate: (T) -> Boolean): T? {
        if (itemCount > 0)
            return dataList.firstOrNull(predicate)
        return null
    }

    override fun getItemCount(): Int {
        return if (listDiffer != null) listDiffer!!.currentList.size else super.getItemCount()
    }

    fun allNoChecked() {
        if (itemCount <= 0)
            return
        for (i in 0 until itemCount) {
            checkedArray.put(i, false)
        }
        notifyDataSetChanged()
    }

    var itemDataCallback: ((holder: ViewHolder?, t: T?, position: Int) -> Unit)? = null

    var itemDataPartUpdateCallback: ((holder: ViewHolder?, t: T?, position: Int, payloads: MutableList<Any>) -> Unit)? = null

    var itemCreateCallback: ((holder: ViewHolder?, viewType: Int) -> Unit)? = null

    constructor(ctx: Context, data: List<T>, @LayoutRes id: Int) : super(ctx, data) {
        layoutId = id
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val holder = ViewHolder(ViewUtil.inflateView(parent.context, layoutId, parent))
        itemCreateCallback?.invoke(holder, viewType)
        return holder
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int, payloads: MutableList<Any>) {
        val t = getItem(position)
        holder.itemView.setTag(R.id.refAdapter, this)
        if (payloads.isEmpty()) {
            itemDataCallback?.invoke(holder, t, position)
        } else {
            if (itemDataPartUpdateCallback == null)
                itemDataCallback?.invoke(holder, t, position)
            else
                itemDataPartUpdateCallback?.invoke(holder, t, position, payloads)
        }
        holder.itemView.setTag(R.id.refAdapter, null)
    }

    override fun bindDataForView(holder: ViewHolder?, t: T?, position: Int) {
        holder?.itemView?.setTag(R.id.refAdapter, this)
        itemDataCallback?.invoke(holder, t, position)
        holder?.itemView?.setTag(R.id.refAdapter, null)
    }

    override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
        super.onDetachedFromRecyclerView(recyclerView)
        itemDataCallback = null
        attachRv = null
    }

    var attachRv: RecyclerView? = null

    override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
        super.onAttachedToRecyclerView(recyclerView)
        attachRv = recyclerView
    }

    fun onDestroy() {
        itemCreateCallback = null
        itemDataCallback = null
        release()
    }
}